package com.dizner.androidcartest;

import android.os.Handler;
import android.util.Log;

import com.google.android.things.pio.Gpio;
import com.google.android.things.pio.PeripheralManager;
import com.google.android.things.userdriver.sensor.UserSensorDriver;
import com.google.android.things.userdriver.sensor.UserSensorReading;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * hc-sr04超声波测距模块
 */
public class Hcsr04 implements AutoCloseable, UserSensorDriver {
    private static final String TAG = Hcsr04.class.getSimpleName();
    private Gpio trigGpio, echoGpio;
    //    private Handler handler = new Handler();
    private static final int pauseInMicro = 12;

    private float distanceInCm;

    private Hcsr04(String sensorName, String trigPin, String echoPin) throws IOException {
        try {
            PeripheralManager service = PeripheralManager.getInstance();
            this.sensorName = sensorName;
            trigGpio = service.openGpio(trigPin);
            echoGpio = service.openGpio(echoPin);
            trigGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
            echoGpio.setDirection(Gpio.DIRECTION_IN);

            trigGpio.setActiveType(Gpio.ACTIVE_HIGH);
//            echoGpio.setActiveType(Gpio.ACTIVE_HIGH);
//            echoGpio.setEdgeTriggerType(Gpio.EDGE_BOTH);
        } catch (IOException e) {
            throw e;
        }
    }

    public static Hcsr04 getInstance(String sensorName, String trigPin, String echoPin) throws IOException {
        return new Hcsr04(sensorName, trigPin, echoPin);
    }

    @Override
    public void close() throws Exception {
        isClosed = true;
        try {
            trigGpio.close();
            echoGpio.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        try {
            trigGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
            echoGpio.setDirection(Gpio.DIRECTION_IN);

            trigGpio.setActiveType(Gpio.ACTIVE_HIGH);
//            echoGpio.setActiveType(Gpio.ACTIVE_HIGH);
//            echoGpio.setEdgeTriggerType(Gpio.EDGE_BOTH);
            if (!startTrigger.isAlive()) {
                startTrigger.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private boolean isClosed;
    private String sensorName;
    private Thread startTrigger = new Thread() {
        @Override
        public void run() {
            while (!isClosed) {

            }

        }
    };

    public float getDistance() {
        try {

            float distanceInCm = 0;
            for (int i = 0; i < 5; i++) {
                int lowCount = 5000;
                trigGpio.setValue(true);
                TimeUnit.MICROSECONDS.sleep(pauseInMicro);
                trigGpio.setValue(false);
                while (!echoGpio.getValue()) {
                    if (lowCount <= 0) {
                        break;
                    }
                    Log.i(TAG, "测距离  A");
                    lowCount--;
                }
                long startTime = System.nanoTime();
                while (echoGpio.getValue()) {
                    Log.i(TAG, "测距离  B");
                }
                long ellapsedTime = System.nanoTime() - startTime;
                ellapsedTime = TimeUnit.NANOSECONDS.toMicros(ellapsedTime);
                float tempDistanceInCm = ellapsedTime / 58f;
//                distanceInCm = ellapsedTime / 58;
                distanceInCm += tempDistanceInCm;
            }
            Log.i(TAG, "距离（CM） = " + distanceInCm / 5f);
            return distanceInCm / 5f;
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return 0;
    }

    private List<OnHCSensorHasDataListener> listenerList;

    public Hcsr04 register(OnHCSensorHasDataListener... listener) {
        if (listenerList == null) {
            listenerList = new ArrayList<>();
        }
        listenerList.addAll(Arrays.asList(listener));
        return this;
    }

    interface OnHCSensorHasDataListener {
        /**
         * @param sensorName
         * @param distance   距离CM
         */
        void onHcSeneorHasData(String sensorName, float distance);
    }


    public float[] getProximityDistance() {
        return new float[]{distanceInCm};
    }

    @Override
    public UserSensorReading read() throws IOException {
        return new UserSensorReading(new float[]{distanceInCm});
    }
}
